package com.rengwuxian.coursecoroutines._2_structured_concurrency

import kotlinx.coroutines.runBlocking
import java.util.concurrent.CountDownLatch
import kotlin.concurrent.thread

/**
 * 线程的交互式结束：interrupt()
 * Thread.interrupt()、Thread.isInterrupted()、Thread.sleep()
 *
 * thread.interrupt() 是让线程自杀，而不是杀线程，是不会导致线程直接结束的。
 * 是一个通知，一个中断标记（已中断）
 * 然后线程内部设置检查点检查该标记，是否需要终止线程。
 * 线程内部可以决定随时终止线程。
 *
 * 检查点如何判断：使用 isInterrupted or Thread.currentThread().isInterrupted(lambda表达式的限制)
 * 可以使用Thread()方法的匿名子类，直接调用isInterrupted
 * 检查点选择：线程中耗时操作之前设置，提前终结线程的目的就是为了节省资源。（关键位置）
 *
 * interrupt() 线程的终结，并不是简单的return，还需要做收尾清理工作（stop()无法做到）
 * 可以考虑：一些文件的处理、图片的滤镜处理等恢复、关闭连接等。
 *
 * 附：Thread内部调用interrupted()方法判断是否中断，第一次调用会返回true，但第二次就返回false了。
 *    而isInterrupted，多次都会返回true。
 *
 * 使用交互式结束线程，程序内部会比较安全。
 *
 * 没有存在使用stop()的紧急场景。其副作用不可预期。
 *
 * thread.interrupt()之后，线程内部的Thread.sleep(200) 使用的时候，会抛出异常。
 * 机制：线程出于等待状态的时候，线程会立即抛出异常InterruptedException。强行打断。
 * 所以，Thread.sleep(200) 通常包着try catch的，对中断函数的订阅。
 * 等待类型的函数，本身没有意义，可以直接打断，非常安全。被动地、自动地响应中断状态的改变。
 *   try {
 *         Thread.sleep(200)
 *       } catch (e: InterruptedException) {
 *         println("isInterrupted: $isInterrupted")
 *         println("Clearing ...")
 *         return
 *       }
 * sleep在遇到中断的时候，除了会立即抛出异常，也会立即重置线程的中断状态，会把线程的中断状态重新改回false。
 * 上面代码打印：
 * Thread: I'm running!
 * isInterrupted: false
 * Clearing ...
 *
 * 上面是java的代码，kotlin代码中取消了强制捕获异常的机制了。
 *
 * 不止是sleep，java中所有等待性质的函数都会抛异常，比如：
 * lock.wait()
 * thread.join()
 * CountDownLatch().await()
 */
fun main() = runBlocking<Unit> {
  val thread = object : Thread() {
    override fun run() {
      println("Thread: I'm running!")
      try {
        Thread.sleep(200)
      } catch (e: InterruptedException) {
        println("isInterrupted: $isInterrupted")
        println("Clearing ...")
        return
      }
      val lock = Object()
      try {
        lock.wait()
      } catch (e: InterruptedException) {
        println("isInterrupted: $isInterrupted")
        println("Clearing ...")
        return
      }
      val newThread = thread {

      }
      newThread.join()
      val latch = CountDownLatch(3)
      latch.await()
      /*var count = 0
      while (true) {
        if (isInterrupted) {
          // clear
          return
        }
        count++
        if (count % 100_000_000 == 0) {
          println(count)
        }
        if (count % 1_000_000_000 == 0) {
          break
        }
      }*/
      println("Thread: I'm done!")
    }
  }.apply { start() }
  Thread.sleep(100)
  thread.interrupt()
}